package com.bw.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.bw.pojo.Coupon;
import com.bw.pojo.Events;
import com.bw.pojo.User;
import com.bw.result.R;
import com.bw.service.Couponervice;
import com.bw.service.EventsService;
import com.bw.service.UcService;
import com.bw.service.UserService;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/user")
@CrossOrigin
public class UserController {
    //spring注入service业务对象
    @Autowired
    private UserService userService;

    //spring注入service业务对象
    @Autowired
    private Couponervice couponervice;

    //spring注入service业务对象
    @Autowired
    private UcService ucService;

    //spring注入service业务对象
    @Autowired
    private EventsService eventsService;

    //spring注入redis操作模板
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private Redisson redisson;



    //spring注入rabbitMQ操作模板
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 登录验证
     *
     * @param uname
     * @param pwd
     * @return
     */
    @GetMapping("/login/{uname}/{pwd}")
    public R login(@PathVariable String uname, @PathVariable String pwd) {
        //创建条件映射对象
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        //设置映射条件
        wrapper.eq("uname", uname);
        wrapper.eq("pwd", pwd);
        //调用service业务对象 判断用户是否存在
        User dbUser = userService.getOne(wrapper);
        //用户不存在
        if (dbUser == null) {
            //提示用户账号密码错误 响应返回结果
            return R.error("用户名或密码错误,请重新输入!");
        } else {
            //用户存在 响应返回结果
            return R.ok(dbUser.getUid());
        }
    }

    /**
     * 活动名称查询
     *
     * @return
     */
    @GetMapping("/selectEventList")
    public R selectEventList() {
        //调用service业务对象 查询活动列表 响应返回结果
        return R.ok(eventsService.list());
    }

    /**
     * 根据优惠券id获取优惠券信息
     *
     * @param cid
     * @return
     */
    @GetMapping("/selectCouponById/{cid}")
    public R selectCouponById(@PathVariable Integer cid) {
        //调用service业务对象 根据优惠券id获取优惠券信息
        Coupon dbCoupon = couponervice.getById(cid);
        //响应返回结果
        return R.ok(dbCoupon);
    }

    /**
     * 根据搞活动id 获取活动信息 判断是否在活动时间范围内
     *
     * @param eid
     * @return
     */
    @PostMapping("/thinkTime/{eid}")
    public R thinkTime(@PathVariable Integer eid) {
        //调用service业务对象 根据活动id获取详细活动信息
        Events dbEvent = eventsService.getById(eid);
        //获取当前时间 判断是否大于活动开始时间
        Date date = new Date();
        if (date.after(dbEvent.getStarttime())) {
            //到活动开始时间 判断活动是否结束(当前时间在结束时间之后)
            if (date.before(dbEvent.getEndtime())) {
                //在活动时间内 响应返回结果
                return R.ok(dbEvent.getCid());
            } else {
                //活动已过期 相应返回结果
                return R.error("活动已过期,请下次参与");
            }
        } else {
            //当前时间小于活动起始时间(未到活动开始时间) 响应返回结果
            return R.error("未到活动开始时间,请耐心等待");
        }
    }

    /**
     * 获取当前登录人信息(根据id获取登录人详细信息)
     *
     * @param uid
     * @return
     */
    @GetMapping("/selectUserById/{uid}")
    public R selectUserById(@PathVariable Integer uid) {
        //调用service业务对象 完成根据用户id获取用户详细信息
        User dbUser = userService.getById(uid);
        //响应返回结果
        return R.ok(dbUser);
    }

    /**
     * 活动详情(根据活动id获取优惠券详情)
     *
     * @param eid
     * @return
     */
    @GetMapping("/selectCouponByEid/{eid}")
    public R selectCouponByEid(@PathVariable Integer eid) {
        //调用service业务对象 完成根据活动id获取活动详情
        Events dbEvents = eventsService.getById(eid);
        //调用service业务对象 完成根据优惠券id获取优惠券详情
        Coupon dbCoupon = couponervice.getById(dbEvents.getCid());
        //相应返回结果
        return R.ok(dbCoupon);
    }

    /**
     * 查询优惠券列表
     *
     * @return
     */
    @GetMapping("/selectCouponList")
    public R selectCouponList() {
        //存入到redis中
        for (Coupon coupon : couponervice.list()) {
            redisTemplate.opsForHash().put("coupon",coupon.getCid(),coupon.getNum());
        }
        //调用service业务对象 完成优惠券列表的查询 响应返回结果
        return R.ok(couponervice.list());
    }

    /**
     * 判断优惠券库存是否充足
     *
     * @param cid
     * @return
     */
    @GetMapping("/isSellOut/{cid}")
    public R isSellOut(@PathVariable Integer cid) {
        //调用service业务对象 根据优惠券id 获取优惠券详细信息
        Coupon dbCoupon = couponervice.getById(cid);
        //判断优惠券是否充足
        if (dbCoupon.getNum() <= 0) {
            //库存不足 响应返回结果
            return R.error("优惠券已抢完,谢谢参与");
        }
        return R.ok();

    }

    /**
     * 用户抢购优惠券 操作
     *
     * @param uid
     * @return
     */
    @PostMapping("/insterLog/{uid}")
    public R insterLog(@PathVariable Integer uid) {
        //调用service业务对象 根据前端传回的用户id 获取抢购对象的详细信息
        User dbUser = userService.getById(uid);
        //获取redis操作模板 根据键值对 (键:用户id) 判断用户本日是否抢购过优惠券
        Object val = redisTemplate.opsForValue().get(dbUser.getUid() + "");
        //计算一天还剩多少秒 (LocalDateTime和ChronoUnit为1.8新增)
        LocalDateTime midnight = LocalDateTime.now().plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
        long seconds = ChronoUnit.SECONDS.between(LocalDateTime.now(), midnight);//一天还剩余多少秒
        //该用户今日还未抢购优惠券
        if (val == null) {
            //用户今日还未抢购过优惠券 获取redis操作模板 将用户对象存储到redis中 次数初始化为1 并设置过期时间
            redisTemplate.opsForValue().set(dbUser.getUid() + "", 1, seconds, TimeUnit.SECONDS);
            return R.ok();
        }
        //该用户今日成功抢购优惠卷次数为1时
        if (Integer.parseInt(val.toString()) == 1) {
            //获取redis操作模板 重新设置用户今日抢购次数+1 并设置过期时间
            redisTemplate.opsForValue().set(dbUser.getUid() + "", 2, seconds, TimeUnit.SECONDS);
            return R.ok();
        }
        //该用户今日成功抢购优惠卷次数为2时
        //用户抢购次数已满 响应返回结果
        return R.error("您今日抢购已满,请明日再来");
    }


    /**
     * rabbitMQ发送消息
     *
     * @param cid
     */
    @PostMapping("/sendMessage/{cid}")
    public void sendMessage(@PathVariable Integer cid) {
        String val ="coupon";
        //获取锁
        RLock lock = redisson.getLock(val + cid);
        try {
            //开始加锁
            lock.lock();
            //获取redis操作模板 根据大key小键 获取值(redis存储的优惠券的值) 删减redis存储的优惠券库存
            int o = (int) redisTemplate.opsForHash().get(val, cid);
            redisTemplate.opsForHash().put(val,cid,o-1);
            //获取rabbitMQ模板 发送消息
            rabbitTemplate.convertAndSend("bw", cid);
            System.out.println("rabbitMQ发送新消息,当前时间: " + new Date());
        } catch (Exception e){
            throw new RuntimeException(e);
        } finally {
            //解锁
            lock.unlock();
        }

    }


























}



























